home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-01-02 | 16.4 KB | 895 lines | [TEXT/????] |
- //
- // XSITE.CPP
- //
- // Copyright (C) Microsoft Corporation, 1996
- //
- #include "headers.h"
- #include <ctype.h>
- #include "MacMisc.h"
- #include "CActiveXScheduler.h"
-
- static CCodeDownload* CodeDownload;
- static void toLower(char* src);
- static LPOLESTR StrDup(LPCOLESTR psz);
-
-
- #pragma mark === CBaseSite::Construction & Destruction ===
-
- /*************************** Construction/Destruction *****************/
-
- //
- // CBaseSite::CreateCBaseSite
- //
-
- CXSite *CXSite::CreateSite(void)
- {
- return new CXSite();
- }
-
-
- //
- // CBaseSite::CBaseSite
- //
-
- CXSite::CXSite(void)
- {
- m_ClientInstance = 0L;
- m_pszCodeURL = NULL;
- m_BaseURL = NULL;
- m_dwMinimumVersion = 0L;
- m_fHaveInitialStream = false;
-
-
- #ifdef PLUGIN_ADAPTER
- m_pInitialDataStreamNotify = NULL;
- m_pUnattachedList = NULL;
- #endif
-
- m_punkObject = NULL;
-
- mUnkOuter = nil;
- mContainerP = nil;
- mContainerData = NULL;
- mObjSiteP = NULL;
- mControlP = NULL;
- mPropertyBagP = NULL;
-
- mContextCount = 1;
- mCachedDraw = false;
- mCachedContextChange = false;
- mCachedActiveContextID = InvalidContextID;
-
- mHavePort = false;
- mOldPortState.ClipRgn = NULL;
- mBindHostP = NULL;
- mThreadScheduler = NULL;
- mDestroyed = false;
- }
-
-
- //
- // CBaseSite::~CBaseSite
- //
-
- CXSite::~CXSite(void)
- {
- #ifdef PLUGIN_ADAPTER
- if (m_pInitialDataStreamNotify != NULL)
- delete m_pInitialDataStreamNotify;
- #endif
- if (m_BaseURL != NULL)
- CoTaskMemFree(m_BaseURL);
- if (m_pszCodeURL != NULL)
- // CoTaskMemFree(m_pszCodeURL);
- DisposePtr(m_pszCodeURL);
-
- if ( mContainerP )
- mContainerP->Release();
- if ( mBindHostP )
- delete mBindHostP;
- }
-
-
- #pragma mark === CBaseSite::Non Interface functions ===
-
- //
- // CBaseSite::AddParam
- //
-
- STDMETHODIMP
- CXSite::AddParam (Char8* inName, Char8* inValue)
- {
- LPOLESTR LowerCaseName = StrDup(inName);
-
- if ( LowerCaseName )
- toLower(LowerCaseName);
- else
- return E_OUTOFMEMORY;
-
- if ( !mPropertyBagP )
- {
- if ((mPropertyBagP = new CPropertyBag()) == NULL)
- return E_OUTOFMEMORY;
- }
-
- if (strcmp(LowerCaseName, "codebase") == 0)
- {
- if ((m_pszCodeURL = (LPOLESTR)StrDup((Char8*)inValue)) != NULL)
- {
- GetVersionFromURL(m_pszCodeURL, &m_dwMinimumVersion);
- }
- }
- else if (strcmp(LowerCaseName, "classid") == 0)
- {
- toLower(inValue);
- if( strncmp(inValue, "clsid:", 6) == 0)
- CLSIDFromString((Char8*)inValue + 6, &m_clsid);
- }
- else
- {
- mPropertyBagP->AddParam(LowerCaseName, inValue );
- }
- DisposePtr(LowerCaseName);
-
- return S_OK;
- }
-
-
- //
- // CBaseSite::FindControl
- //
- #define kCLSIDConst "CLSID\\"
-
- STDMETHODIMP
- CXSite::FindControl(void)
- {
- HKEY hKey;
- char* CLSIDString;
- char Key[256];
-
- StringFromCLSID(m_clsid, &CLSIDString);
- Key[0] = '\0';
- strcat(Key, kCLSIDConst);
- strcat(Key, CLSIDString);
- #undef CoTaskMemFree // StringFromCLSID used CoTaskMemAlloc so don't us debug version
- CoTaskMemFree(CLSIDString);
- #ifdef CHECKMEMORYLEAKS
- #define CoTaskMemFree DebugCoTaskMemFree
- #endif
- if (RegOpenKey(HKEY_CLASSES_ROOT, Key, &hKey) == S_OK)
- {
- RegCloseKey(hKey);
- return S_OK;
- }
- else if (m_pszCodeURL == NULL ||
- GetFileTypeFromExtension(m_pszCodeURL) == FILEXTN_UNKNOWN)
- return E_UNEXPECTED;
-
- return S_OK;
- }
-
- //
- // CBaseSite::CreateControl
- //
-
- STDMETHODIMP
- CXSite::CreateControl(Boolean8 inDoDownload)
- {
- ErrorCode Result;
- LPUNKNOWN punkPersist;
-
- if (m_punkObject != NULL || mDestroyed)
- return E_ABORT;
-
- if(!mBindHostP)
- mBindHostP = new CBindHost(this);
- // Attempt to create the object. The latest OLE Controls guidelines only
- // require the object to support IUnknown.
- if (FAILED(Result = CoCreateInstance(m_clsid, NULL, CLSCTX_INPROC_SERVER,
- IID_IUnknown, (LPVOID *) &m_punkObject)))
- {
- // if we need to download, and the client says it is okay, do it
- // otherwise, just pass the error back so the client can deal with it
- if ( Result == REGDB_E_CLASSNOTREG || Result == CO_E_DLLNOTFOUND)
- {
- if (m_pszCodeURL == NULL ||
- GetFileTypeFromExtension(m_pszCodeURL) == FILEXTN_UNKNOWN)
- return E_UNEXPECTED;
- if(!inDoDownload )
- return Result;
-
- // Create the download object for this container if not already available.
- if (CodeDownload == NULL)
- {
- if ((CodeDownload = new CCodeDownload()) == NULL)
- return E_FAIL;
- }
- AddRef(); // accout for this pointer
- CodeDownload->QueueDownload(this);
- return E_PENDING;
- }
- return E_FAIL;
- }
-
- // See if this is an in-proc object
- if (SUCCEEDED(m_punkObject->QueryInterface(IID_IObjectWithSite, (LPVOID *) &mObjSiteP)))
- {
- mObjSiteP->SetSite((IUnknown*) (void*) this);
- if (FAILED(m_punkObject->QueryInterface(IID_IControl, (LPVOID *) &mControlP)))
- mControlP = nil;
- }
- else
- mObjSiteP = NULL;
-
- if ( !mControlP )
- goto CreateFailure;
-
- if (SUCCEEDED(m_punkObject->QueryInterface(IID_IPersistPropertyBag,(LPVOID *) &punkPersist)))
- {
- Result = ((LPPERSISTPROPERTYBAG) punkPersist)->Load( mPropertyBagP, NULL);
- punkPersist->Release();
-
- }
- #ifdef PLUGIN_ADAPTER
- else if (m_pInitialDataStreamNotify != NULL &&
- SUCCEEDED(m_punkObject->QueryInterface(IID_IPersistStream,
- (LPVOID *) &punkPersist)))
- {
- m_pInitialDataStreamNotify->m_SeekPosition = sizeof(CLSID);
- Result = ((LPPERSISTSTREAM) punkPersist)->Load((LPSTREAM)
- m_pInitialDataStreamNotify);
- punkPersist->Release();
- }
- delete m_pInitialDataStreamNotify;
- m_pInitialDataStreamNotify = NULL;
- #endif
-
- if (FAILED(Result))
- goto CreateFailure;
-
- if ( mCachedContextChange )
- {
- UInt32 ContextID;
- Int32 Index = 0;
-
- while ( GetContextID(++Index, &ContextID))
- {
- mControlP->OnContextChange(ContextID, AddContext);
- if (ContextID == mCachedActiveContextID)
- mControlP->OnContextChange(ContextID, ActivateContext);
- }
-
- mCachedContextChange = false;
- }
-
- if ( mCachedDraw )
- {
- DrawControl();
- mCachedDraw = false;
- }
-
-
- return S_OK;
-
- // Cleanup after anything that we've already done and unload the object.
- CreateFailure:
- DestroyControl();
- return E_FAIL;
-
- }
-
-
- //
- // CBaseSite::DestroyControl
- //
-
- STDMETHODIMP
- CXSite::DestroyControl(void)
- {
- mDestroyed = true;
-
- if ( mPropertyBagP )
- ReleaseAndNull(mPropertyBagP);
-
- if(mBindHostP != NULL)
- mBindHostP->AbortBindings();
-
- if (mControlP != NULL)
- ReleaseAndNull(mControlP);
-
- if (mObjSiteP != NULL)
- {
- mObjSiteP->SetSite(NULL);
- ReleaseAndNull(mObjSiteP);
- }
-
- SafeReleaseAndNull(m_punkObject);
- CoFreeUnusedLibraries(); // unload the com object if not used
-
- return S_OK;
- }
-
-
- //
- // CBaseSite::SetContainerData
- //
- // Sets the container data for the site
- //
-
- STDMETHODIMP
- CXSite::SetContainerData(IUnknown* inUnkOuter, void *inContainerData)
- {
- mUnkOuter = inUnkOuter;
- if (mContainerP)
- mContainerP->Release();
- mUnkOuter->QueryInterface(IID_IContainer, &mContainerP);
- mContainerData = inContainerData;
- return S_OK;
- }
-
-
- //
- // CBaseSite::GetContainerData
- //
- // Returns the container
- //
-
- STDMETHODIMP
- CXSite::GetContainerData(void** outContainerData)
- {
- *outContainerData = mContainerData;
- return S_OK;
- }
-
- //
- // CBaseSite::SetBaseURL
- //
- // Sets the base URL for this site
- //
-
- STDMETHODIMP
- CXSite::SetBaseURL(Char8* inURL)
- {
- if ( m_BaseURL )
- {
- CoTaskMemFree(m_BaseURL);
- m_BaseURL = nil;
- }
-
- m_BaseURL = OleStrdup(inURL);
-
- return S_OK;
- }
-
- //
- // CBaseSite::DrawControl
- //
-
- void CXSite::DrawControl(void)
- {
- if ( mControlP )
- {
- DrawContext Context = {BeginPortType};
- UInt32 ContextID;
- long Index = 1;
-
- while( GetContextID(Index++, &ContextID) )
- {
- AcquireContext(ContextID, &Context);
- mControlP->Draw(&Context);
- ReleaseContext(&Context);
- }
- }
- else
- mCachedDraw = true;
- }
-
-
- //
- // CBaseSite::SavePortState
- //
-
- void CXSite::SavePortState(PlatformPort* Port)
- {
- // Save off the current port
- ::GetPort(&mSavePort);
-
- // Set the current port to the one requested
- ::SetPort(Port);
-
- // Save off the port rect and clip
- mOldPortState.PortRect = Port->portRect;
- mOldPortState.ClipRgn = NewRgn();
- ::GetClip(mOldPortState.ClipRgn);
-
- // Save off the pen state
- ::GetPenState(&mOldPortState.PenState);
- mOldPortState.TextFont = Port->txFont;
- mOldPortState.TextMode = Port->txMode;
- mOldPortState.TextSize = Port->txSize;
- mOldPortState.TextFace = Port->txFace;
- ::GetForeColor(&mOldPortState.ForeColor);
- ::GetBackColor(&mOldPortState.BackColor);
- }
-
-
- //
- // CBaseSite::RestorePortState
- //
-
- void CXSite::RestorePortState(void)
- {
- // Undo everything we did to "thePort" in AcquirePort.
- ::SetOrigin(mOldPortState.PortRect.left, mOldPortState.PortRect.top);
- if (mOldPortState.ClipRgn)
- {
- ::SetClip(mOldPortState.ClipRgn);
- ::DisposeRgn(mOldPortState.ClipRgn);
- mOldPortState.ClipRgn = NULL;
- }
-
- // Restore the current state of things
- ::SetPenState(&mOldPortState.PenState);
- ::TextFont(mOldPortState.TextFont);
- ::TextFace(mOldPortState.TextFace);
- ::TextMode(mOldPortState.TextMode);
- ::TextSize(mOldPortState.TextSize);
- ::RGBForeColor(&mOldPortState.ForeColor);
- ::RGBBackColor(&mOldPortState.BackColor);
-
- // Set back to original port
- ::SetPort(mSavePort);
-
- }
-
-
- //
- // CBaseSite::GetContextID
- //
- // all containers MUST OVERRIDE this
-
- Boolean8
- CXSite::GetContextID(Int32 inContextIndex, UInt32* outContextID)
- {
- #pragma unused (inContextIndex, outContextID)
- return false;
- }
-
-
- #pragma mark === CBaseSite::IUnknown Interfaces ===
-
- /************************* IUnknown Interfaces *************************/
- //
- // CBaseSite::IUnknown::QueryInterface
- //
- // Returns a pointer to the specified interface on a component to which a
- // client currently holds an interface pointer.
- //
- STDMETHODIMP
- CXSite::QueryInterface(REFIID inRefID, void** outObj)
- {
- ErrorCode Result = CBaseCOM::QueryInterface( inRefID, outObj);
-
- if ( Result == E_NOINTERFACE )
- {
- void* pv = nil;
-
- if ( inRefID == IID_IControl )
- pv = (void*)(IControl*) this;
- else if ( inRefID == IID_IContainerSite )
- pv = (void*)(IContainerSite*) this;
- else if (inRefID == IID_IServiceProvider)
- pv = (void*)(LPSERVICEPROVIDER) this;
- else if (inRefID == IID_IBindHost)
- pv = (void*)(LPBINDHOST) mBindHostP;
- else if (inRefID == IID_IThreadScheduler)
- pv = (void*)(IThreadScheduler*) this;
-
- *outObj = pv;
-
- if ( pv )
- {
- ((IUnknown*) pv)->AddRef();
- Result = S_OK;
- }
- }
-
- return Result;
-
- }
-
-
-
- #pragma mark === CBaseSite::IContainerSite Interfaces ===
-
- //
- // CBaseSite::IContainerSite::GetContainer
- //
- // Returns the container
- //
-
- STDMETHODIMP
- CXSite::GetContainer(IContainer** outContainer)
- {
- // Caller's responsibility to AddRef the container interface
- *outContainer = mContainerP;
- return S_OK;
- }
-
-
- //
- // CBaseSite::IContainerSite::RequestFocus
- //
- // attempt to manage focus
- //
-
- STDMETHODIMP
- CXSite::RequestFocus ( Boolean8 /* inAcquire */, FocusSet /* inFocus */)
- {
- return E_NOTIMPL;
- }
-
-
- //
- // CBaseSite::RequestSizeChange
- //
- // how to change the controls size
- //
-
- STDMETHODIMP
- CXSite::RequestSizeChange ( Point* /* ioSize */)
- {
- return E_NOTIMPL;
- }
-
- //
- // CBaseSite::OnChange
- //
- // Notification that something of interest changed in the control
- //
-
- STDMETHODIMP
- CXSite::OnChange (ChangeType inChangeType)
- {
- switch (inChangeType)
- {
- case UsedAreaChange:
- {
- DrawContext Context = {BeginPortType};
- UInt32 ContextID;
- long Index = 1;
-
- while( GetContextID(Index++, &ContextID) )
- {
- AcquireContext(ContextID, &Context);
- ::EraseRect(&Context.Location);
- ReleaseContext(&Context);
- }
- }
- break;
- case ViewChange:
- case DataChange:
- default:
- break;
- }
-
- return S_OK; // we don't care here
- }
-
- //
- // CBaseSite::IContainerSite::AcquireContext
- //
-
- STDMETHODIMP
- CXSite::AcquireContext(Uint32 /*inContextID*/, DrawContext* /*outContext*/)
- {
- return E_FAIL;
- }
-
-
- //
- // CBaseSite::IContainerSite::ReleaseContext
- //
-
- STDMETHODIMP
- CXSite::ReleaseContext(DrawContext* inContext)
- {
- #pragma unused (inContext)
-
- if (!mHavePort)
- {
- // Unbalanced GetDC/ReleaseDC calls. Return an error.
- return E_FAIL;
- }
-
- RestorePortState();
-
- mHavePort = FALSE;
-
- return S_OK;
- }
-
-
- //
- // CBaseSite::IContainerSite::SetIdleTime
- //
-
- STDMETHODIMP
- CXSite::SetIdleTime(Int32 inWaitTicks, Uint32 inRefCon)
- {
- CActiveXScheduler* Scheduler = CActiveXScheduler::GetActiveXScheduler(true);
- ErrorCode Result = E_FAIL;
-
- if (Scheduler)
- {
- if (inWaitTicks == RemoveAllIdlers)
- Result = Scheduler->RemoveControl(this);
- else if (inWaitTicks == RemoveIdler)
- Result = Scheduler->RemoveControlByRefCon(this, inRefCon);
- else
- {
- Result = Scheduler->ScheduleControl(inWaitTicks == IdleAfterAllEvents, inWaitTicks, this, inRefCon);
- }
- }
-
- return Result;
- }
-
-
-
- #pragma mark === CBaseSite::IControl Interfaces ===
-
- //
- // CBaseSite::IControl::Draw
- //
- // Calls the embedded object and tells it to paint itself.
- //
-
- STDMETHODIMP
- CXSite::Draw(DrawContext* inContext)
- {
- if ( mControlP )
- mControlP->Draw(inContext);
- else
- mCachedDraw = true;
-
- return S_OK;
- }
-
-
- //
- // CBaseSite::IControl::OnContextChange
- //
- // Adds a context to the control
- //
-
- STDMETHODIMP
- CXSite::OnContextChange(UInt32 inContextID, ContextCommand inCommand)
- {
- if ( mControlP )
- return mControlP->OnContextChange(inContextID, inCommand);
- else
- {
- mCachedContextChange = true;
- if (inCommand == ActivateContext)
- mCachedActiveContextID = inContextID;
- else if (inCommand == DeactivateContext)
- mCachedActiveContextID = InvalidContextID;
- return S_OK;
- }
- }
-
-
- //
- // CBaseSite::IControl::GetID
- //
- // Returns the ID of the control
- //
-
- STDMETHODIMP
- CXSite::GetID(Int32 inBufferSize, Char8* outID)
- {
- if ( mControlP )
- return mControlP->GetID(inBufferSize, outID);
- else
- {
- outID[0] = 0; // return null string
- return E_FAIL;
- }
- }
-
- //
- // CBaseSite::IControl::GetUsedArea
- //
- // Returns the used area of the control
- //
-
- STDMETHODIMP
- CXSite::GetUsedArea(PlatformRegion* outUsedArea)
- {
- if ( mControlP )
- return mControlP->GetUsedArea(outUsedArea);
- else
- return E_FAIL;
- }
-
- //
- // CBaseSite::IControl::SetFocus
- //
- // Sets or removes focus from this site
- //
-
- STDMETHODIMP
- CXSite::SetFocus(FocusCommand inCommand, FocusSet inFocus)
- {
- ErrorCode theResult = S_OK;
-
- if ( mControlP )
- theResult = mControlP->SetFocus(inCommand, inFocus);
- else
- theResult = E_FAIL;
-
- return theResult;
- }
-
-
- //
- // CBaseSite::IControl::DoMouse
- //
-
- STDMETHODIMP
- CXSite::DoMouse(MouseEventType inMouseET, PlatformEvent* inEvent)
- {
- ErrorCode theResult = S_OK;
-
- if ( mControlP )
- theResult = mControlP->DoMouse(inMouseET, inEvent);
-
- return theResult;
- }
-
-
- //
- // CBaseSite::IControl::DoKey
- //
-
- STDMETHODIMP
- CXSite::DoKey(KeyEventType inKeyET, Char8 inChar, PlatformEvent* inEvent)
- {
- ErrorCode theResult = S_OK;
-
- if ( mControlP )
- theResult = mControlP->DoKey(inKeyET, inChar, inEvent);
-
- return theResult;
- }
-
-
- //
- // CBaseSite::IControl::DoActivate
- //
-
- STDMETHODIMP
- CXSite::DoActivate(ActivateEventType inActiveET, UInt32 inContextID, PlatformEvent* inEvent)
- {
- ErrorCode theResult = S_OK;
-
- if ( mControlP )
- theResult = mControlP->DoActivate(inActiveET, inContextID, inEvent);
-
- return theResult;
- }
-
-
- //
- // CBaseSite::IControl::DoSystemEvent
- //
-
- STDMETHODIMP
- CXSite::DoSystemEvent(PlatformEvent* inEvent)
- {
- ErrorCode theResult = S_OK;
-
- if ( mControlP )
- theResult = mControlP->DoSystemEvent(inEvent);
-
- return theResult;
- }
-
-
- //
- // CBaseSite::IControl::OnIdle
- //
- // pass idle events to the control
- //
-
- STDMETHODIMP
- CXSite::DoIdle(Uint32 IdleRefCon)
- {
- if ( mControlP )
- return mControlP->DoIdle(IdleRefCon);
- else
- return SetIdleTime(RemoveAllIdlers, NULL);
- }
-
-
- #pragma mark === CBaseSite::IServiceProvider Interface ===
-
- //
- // CBaseSite::IServiceProvider::QueryService
- //
-
- STDMETHODIMP
- CXSite::QueryService(REFGUID inRSID, REFIID inRefID, void** outObj)
- {
- ErrorCode Result;
-
- if (inRSID == SID_BindHost)
- {
- // According to the "OLE Controls/COM Objects for the Internet" spec,
- // it's legal for the site to implement this service directly on the
- // site object.
- Result = this->QueryInterface(inRefID, outObj);
- }
- else if ( inRSID == SID_IThreads )
- Result = this->QueryInterface(inRefID, outObj);
- else
- {
- *outObj = NULL;
- Result = E_NOINTERFACE;
- }
-
- return Result;
- }
-
-
- #pragma mark === CBaseSite::IThreadScheduler Interface ===
-
- //
- // CBaseSite::IThreadScheduler::GetScheduler
- //
- STDMETHODIMP
- CXSite::GetScheduler(ProcPtr* outScheduler)
- {
- *outScheduler = mThreadScheduler;
-
- if ( mThreadScheduler )
- return S_OK;
- else
- return S_FALSE;
- }
-
-
-
-
-
- #pragma mark === Static Utility Functions ===
-
- //
- // toLower
- //
-
- static void toLower(char* src)
- {
- for(char * p = src;*p; p++){
- *p = tolower(*p);
- }
- }
-
-
- //
- // StrDup
- //
-
- static LPOLESTR StrDup(LPCOLESTR psz)
- {
- LPOLESTR pszDup;
-
- if ((pszDup = (LPOLESTR) NewPtr(strlen((char *) psz) + 1)) != NULL)
- strcpy((char *) pszDup, (const char *) psz);
-
- return pszDup;
- }
-
-
-